#region Licence
// Copyright (c) 2008 James Gregory (james@jagregory.com)
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
// 
//     * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//     * Neither the name of James Gregory nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

using System.IO;
using antlr;
using Boo.Lang.Parser;
using Microsoft.VisualStudio.Package;

namespace JAGregory.BooPlugin.Language
{
    internal class BooScanner : IScanner
    {
        private TokenStream lexer;

        public void SetSource(string source, int offset)
        {
            TextReader reader = new StringReader(source);

            if (!string.IsNullOrEmpty(source))
                lexer = BooParser.CreateBooLexer(1, "not sure", reader);
        }

        public bool ScanTokenAndProvideInfoAboutIt(TokenInfo tokenInfo, ref int state)
        {
            if (lexer == null) return false;

            IToken token = lexer.nextToken();

            state = 0;

            tokenInfo.Trigger = TokenTriggers.None;
            tokenInfo.StartIndex = token.getColumn() - 1;

            string text = token.getText();

            tokenInfo.EndIndex = string.IsNullOrEmpty(text) ? tokenInfo.StartIndex : tokenInfo.StartIndex + (token.getText().Length - 1); //tokenizer.EndLocation.Column > tokenizer.StartLocation.Column ? tokenizer.EndLocation.Column - 1 : tokenizer.EndLocation.Column;

            switch (token.Type)
            {
                case BooLexer.EOL:
                case BooLexer.EOF:
                    return false;

                //case BooLexer.Error:
                case BooLexer.NEWLINE:
                    goto default;

                case BooLexer.INDENT:
                case BooLexer.DEDENT:
                    tokenInfo.Trigger = TokenTriggers.MatchBraces;
                    goto default;

                case BooLexer.SL_COMMENT:
                    tokenInfo.Type = TokenType.LineComment;
                    tokenInfo.Color = TokenColor.Comment;
                    break;

                case BooLexer.ML_COMMENT:
                    tokenInfo.Type = TokenType.Comment;
                    tokenInfo.Color = TokenColor.Comment;
                    break;

                case BooLexer.DOT:
                    tokenInfo.Trigger = TokenTriggers.MemberSelect;
                    goto case BooLexer.ASSIGN;
                case BooLexer.LPAREN:
                    tokenInfo.Trigger = TokenTriggers.MatchBraces | TokenTriggers.ParameterStart;
                    goto case BooLexer.ASSIGN;
                case BooLexer.RPAREN:
                    tokenInfo.Trigger = TokenTriggers.MatchBraces | TokenTriggers.ParameterEnd;
                    goto case BooLexer.ASSIGN;

                //case BooLexer.LeftBracket:
                //    tokenInfo.Trigger = TokenTriggers.MatchBraces;
                //    goto case BooLexer.Assign;

                //case BooLexer.RightBracket:
                //    tokenInfo.Trigger = TokenTriggers.MatchBraces;
                //    goto case BooLexer.Assign;
                //case BooLexer.LeftBrace:
                //    tokenInfo.Trigger = TokenTriggers.MatchBraces;
                //    goto case BooLexer.Assign;
                //case BooLexer.RightBrace:
                //    tokenInfo.Trigger = TokenTriggers.MatchBraces;
                //    goto case BooLexer.Assign;

                case BooLexer.COMMA:
                    tokenInfo.Trigger = TokenTriggers.ParameterNext;
                    goto case BooLexer.ASSIGN;
                case BooLexer.COLON:
                //case BooLexer.BackQuote:
                //case BooLexer.Semicolon:
                case BooLexer.ASSIGN:
                //case BooLexer.Twiddle:
                //case BooLexer.LessThanGreaterThan:
                    tokenInfo.Type = TokenType.Delimiter;
                    tokenInfo.Color = TokenColor.Text;
                    break;

                case BooLexer.ADD:
                //case BooLexer.AddEqual:
                case BooLexer.SUBTRACT:
                //case BooLexer.SubtractEqual:
                //case BooLexer.Power:
                //case BooLexer.PowerEqual:
                case BooLexer.MULTIPLY:
                //case BooLexer.MultiplyEqual:
                //case BooLexer.FloorDivide:
                //case BooLexer.FloorDivideEqual:
                //case BooLexer.Divide:
                //case BooLexer.DivEqual:
                case BooLexer.MODULUS:
                //case BooLexer.ModEqual:
                //case BooLexer.LeftShift:
                //case BooLexer.LeftShiftEqual:
                //case BooLexer.RightShift:
                //case BooLexer.RightShiftEqual:
                case BooLexer.BITWISE_AND:
                //case BooLexer.BitwiseAndEqual:
                case BooLexer.BITWISE_OR:
                //case BooLexer.BitwiseOrEqual:
                //case BooLexer.Xor:
                //case BooLexer.XorEqual:
                case BooLexer.LESS_THAN:
                case BooLexer.GREATER_THAN:
                //case BooLexer.LessThanOrEqual:
                //case BooLexer.GreaterThanOrEqual:
                //case BooLexer.Equal:
                //case BooLexer.NotEqual:
                    tokenInfo.Type = TokenType.Operator;
                    tokenInfo.Color = TokenColor.Text;
                    break;

                case BooLexer.AND:
                //case BooLexer.KeywordAssert:
                case BooLexer.AS:
                case BooLexer.BREAK:
                case BooLexer.CLASS:
                case BooLexer.CONTINUE:
                case BooLexer.DEF:
                //case BooLexer.KeywordDel:
                case BooLexer.ELIF:
                case BooLexer.ELSE:
                case BooLexer.EXCEPT:
                //case BooLexer.KeywordExec:
                case BooLexer.ENSURE:
                case BooLexer.FOR:
                case BooLexer.FROM:
                //case BooLexer.KeywordGlobal:
                case BooLexer.IF:
                case BooLexer.IMPORT:
                case BooLexer.IN:
                case BooLexer.IS:
                //case BooLexer.KeywordLambda:
                case BooLexer.NOT:
                case BooLexer.OR:
                case BooLexer.PASS:
                //case BooLexer.KeywordPrint:
                case BooLexer.RAISE:
                case BooLexer.RETURN:
                case BooLexer.TRY:
                case BooLexer.WHILE:
                case BooLexer.YIELD:
                case BooLexer.CONSTRUCTOR:
                case BooLexer.DESTRUCTOR:
                    tokenInfo.Type = TokenType.Keyword;
                    tokenInfo.Color = TokenColor.Keyword;
                    break;
                case BooLexer.SINGLE_QUOTED_STRING:
                case BooLexer.DOUBLE_QUOTED_STRING:
                    tokenInfo.Type = TokenType.String;
                    tokenInfo.Color = TokenColor.String;
                    tokenInfo.EndIndex += 2; // allow for quote chars
                    break;
                case BooLexer.TRIPLE_QUOTED_STRING:
                    tokenInfo.Type = TokenType.String;
                    tokenInfo.Color = TokenColor.String;
                    tokenInfo.EndIndex += 6; // allow for quote chars
                    break;
                case BooTokenTypes.WS:
                    tokenInfo.Type = TokenType.WhiteSpace;
                    tokenInfo.Color = TokenColor.Text;
                    break;
                default:
                    tokenInfo.Type = TokenType.Unknown;
                    tokenInfo.Color = TokenColor.Text;
                    return true;
            }

            return true;
        }
    }
}